package com.ds.dsfans.shell.util.adb.device;


import com.ds.dsfans.shell.util.common.ShellUtil;
import com.ds.dsfans.shell.util.common.XmlUtil;
import com.ds.dsfans.shell.util.common.fc.DefultFuction;

import java.io.File;
import java.util.List;

/**
 * 〈功能概述〉<br>
 *
 * @className: Device
 */
public class Device {
    // 系统临时目录
//    private String tempFile = System.getProperty("java.io.tmpdir");
    private String tempFile = "D:\\project\\autoapp\\src\\test\\resources\\";
    //设备号
    private String deviceCode;
    private XmlUtil xmlUtil = null;
    private boolean isCurrent = false;
    // 默认获取元素时间间隔 10 m秒
    private int defualtInterval = 2000;

    private static int second = 2000;
    private static final String space = " ";

    public String getDeviceCode() {
        return deviceCode;
    }


    public void setDeviceCode(String deviceCode) {
        this.deviceCode = deviceCode;
    }


    /*
     * @Description:
     * 获取界面xml信息 返回xml路径 获取元素时要先调用这个方法
     **/
    public Device find() {
        return select(() -> shell("shell /system/bin/uiautomator dump /data/local/tmp/" + deviceCode.hashCode() + "uidump.xml"));
    }

    /*
     * 简洁的界面信息
     * @Author zhangRenHuo
     * @Date 17:35 2020/9/23
     * @param null
     * @return
     */
    public Device findMain() {
        return select(() -> shell("shell /system/bin/uiautomator dump --compressed /data/local/tmp/" + deviceCode.hashCode() + "uidump.xml"));
    }

    private Device select(DefultFuction defultFuction) {
        String fileName = deviceCode.hashCode() + "uidump.xml";
        defultFuction.start();
        String path = tempFile + fileName;
        shell("pull /data/local/tmp/" + fileName + " " + tempFile);
        if (null == xmlUtil) {
            xmlUtil = new XmlUtil(path, deviceCode);
        } else {
            xmlUtil.reset(path);
        }
        return this;
    }

    public Device parentId(String id) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildAndId(id));
    }

    public Device childId(String id) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildAndId(id));
    }

    public Device className(String className) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByClassName(className));
    }

    public Device resourceId(String resourceId) throws InterruptedException {
        return defFunction(() -> xmlUtil.findById(resourceId));
    }

    public Device parentClassName(String className) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByParentAndClassName(className));
    }

    public Device childClassName(String className) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildAndClassName(className));
    }

    public Device text(String text) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByText(text));
    }

    public Device parentText(String text) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByParentAndText(text));
    }

    public Device childText(String text) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildAndText(text));
    }

    public Device desc(String desc) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByDesc(desc));
    }

    public Device parentDesc(String desc) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByParentAndDesc(desc));
    }

    public Device childDesc(String desc) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildAndDesc(desc));
    }

    /*
     * @Description:
     * 获取子节点
     * @return
     **/
    public Device child() throws InterruptedException {
        return defFunction(() -> xmlUtil.getChild());
    }

    /*
     * @Description:
     * 根据子节点数查询 函数式
     * @return
     **/
    public Device childNum(Integer num) throws InterruptedException {
        return defFunction(() -> xmlUtil.findByChildNum(num));
    }

    /*
     * @Description:
     * 函数式接口调用
     * @return
     **/
    private Device defFunction(DefultFuction defultFuction) throws InterruptedException {
        boolean isOk = false;
        int interval = this.defualtInterval;
        while (!isOk) {
            defultFuction.start();
            if (xmlUtil.getElements().isEmpty()) {
                find();
                Thread.sleep(second);
                interval += -second;
                if (interval <= 0) {
                    isOk = true;
                }
                continue;
            }
            // 避免未找到元素
            defultFuction.start();
            isOk = true;
        }
        return this;
    }

    /*
     * @Description:
     * 根据条件最终返回对应的节点集合
     * @return
     **/
    public List<Node> getNodes() {
        return xmlUtil.getNodes();
    }

    // 0 2 1 3
    public void click(Integer x1, Integer x2, Integer y1, Integer y2) {
        int x = (x1 + x2) / 2;
        int y = (y1 + y2) / 2;
        shell("shell input tap " + x + " " + y);
    }

    public void click(Integer x, Integer y) {
        shell("shell input tap " + x + " " + y);
    }

    /*
     * @Description:滑动
     * @return
     **/
    public void swipe(Integer startX, Integer startY, Integer endX, Integer endY) {
        shell("shell input swipe" + space + startX + space + startY + space + endX + space + endY + space + "500");
    }

    /*
     * @Description:滑动
     * @Author
     * @Date
     * @return
     **/
    public void swipe(Integer startX, Integer startY, Integer endX, Integer endY, Integer ms) {
        shell("shell input swipe" + space + startX + space + startY + space + endX + space + endY + space + ms);
    }

    /*
     * @Description:根据包名加active路径启动app
     * @Author
     * @Date
     * @return
     **/
    public void runApp(String packagePath) {
        shell("shell am start -n " + packagePath);
    }

    /*
     * @Description:关闭app
     * @return
     **/
    public void stopApp(String packageName) {
        shell("shell am force-stop " + packageName);
    }

    public String listAppPackage() {
        return shell("shell pm list packages");
    }

    /*
     * @Description:获取设备分辨率
     * @Author
     * @Date
     * @return
     **/
    public DeviceSize getSize() {
        String size = shell("shell wm size");
        String[] split = size.split(":");
        if (split.length > 1) {
            String[] xes = split[1].trim().split("x");
            DeviceSize deviceSize = new DeviceSize();
            deviceSize.setWidth(Integer.parseInt(xes[0]));
            deviceSize.setHeigth(Integer.parseInt(xes[1]));
            return deviceSize;
        }
        return null;
    }

    /*
     * @Description:获取设备id
     * @Author
     * @Date
     * @return
     **/
    public String getAndroidId() {
        String androidId = shell("shell settings get secure android_id").trim();
        return androidId;
    }

    /*
     * @Description:设置剪贴板内容
     * @Author
     * @Date
     * @param null
     * @return
     */
    public void setClipper(String text) {
        shell("shell am broadcast -a clipper.set -e text \"" + text + "\"");
    }

    /**
     * @return
     * @Description: 获取剪贴板内容
     */
    public String getClipper() {
        return shell("shell am broadcast -a clipper.get").trim();
    }

    /**
     * 左滑
     */
    public void leftSwipe() {
        DeviceSize size = getSize();
        swipe(size.getWidth() / 2, size.getHeigth() / 2, 0, size.getHeigth() / 2);
    }

    /**
     * 右滑
     */
    public void rightSwipe() {
        DeviceSize size = getSize();
        swipe(0, size.getHeigth() / 2, size.getWidth(), size.getHeigth() / 2);
    }

    /**
     * 上滑
     */
    public void topSwipe() {
        DeviceSize size = getSize();
        swipe(size.getWidth() / 2, size.getHeigth() / 2, size.getWidth() / 2, 0);
    }

    /**
     * 下滑
     */
    public void bottomSwipe() {
        DeviceSize size = getSize();
        swipe(size.getWidth() / 2, size.getHeigth() / 2, size.getWidth() / 2, size.getHeigth());
    }

    /**
     * 返回
     */
    public void back() {
        shell("shell input keyevent 4").trim();
    }

    /**
     * 模拟输入key
     *
     * @param key
     */
    public void key(String key) {
        shell("shell input keyevent " + key);
    }

    /**
     * 文本输入
     *
     * @param msg
     */
    public void input(String msg) {
        shell("shell input text '" + msg + "'");
    }

    /**
     * 设置代理ip  如：192.168.1.200:3128
     *
     * @param proxy
     * @return
     * @Author
     * @Date
     */
    public void setProxy(String proxy) {
        shell("shell settings put global http_proxy " + proxy);
    }

    /**
     * 去掉ip代理
     *
     * @return
     * @Author
     * @Date
     */
    public void cancelProxy() {
        shell("shell settings delete global http_proxy");
        shell("shell settings delete global global_http_proxy_host");
        shell("shell settings delete global global_http_proxy_port");
        shell("reboot");
    }

    /**
     * 截图 -- 图片路径
     */
    public String screenCap() {
        String filePath = tempFile + deviceCode + "img.png";
        File file = new File(filePath);
        if (file.exists()) {
            boolean delete = file.delete();
        }
        shell("shell screencap -p /data/local/tmp/" + deviceCode + "img.png");
        shell("pull /data/local/tmp/" + deviceCode + "img.png " + tempFile);
        return filePath;
    }

    /*
     * @Description:
     * 执行adb命令
     * @Author zhangRenHuo
     * @Date 10:39 2020/8/5
     * @return
     **/
    private String shell(String adb) {
        Process cmd = ShellUtil.adbCmd("-s " + deviceCode + " " + adb);
        String shellOut = ShellUtil.getShellOut(cmd);
        return shellOut;
    }

    private static void err(String str) {
        System.err.println(str);
    }

    private Device() {
    }

    public static Device getDevice(String id) {
        Device device = new Device();
        device.setDeviceCode(id);
        return device;
    }

    public String getTempFile() {
        return tempFile;
    }

    public class DeviceSize {
        private Integer width;
        private Integer heigth;

        public Integer getWidth() {
            return width;
        }

        public void setWidth(Integer width) {
            this.width = width;
        }

        public Integer getHeigth() {
            return heigth;
        }

        public void setHeigth(Integer heigth) {
            this.heigth = heigth;
        }
    }

}
